import { Injectable } from '@nestjs/common';
import { and, eq, ilike } from 'drizzle-orm';
import { BaseService, db, sysDict, type SysDict, sysDictData } from '@nbase/db';
import { BizException } from '@nbase/nest-mods';
import type { IDict, IPaginationResponse } from '@nbase/shared';
import { CreateDictDto } from './dto/create-dict.dto';
import { UpdateDictDto } from './dto/update-dict.dto';
import { QueryDictDto } from './dto/query-dict.dto';
import { toDict, toDictPage } from './dict.mapper';

/**
 * 字典服务
 */
@Injectable()
export class DictService extends BaseService<typeof sysDict> {
  constructor() {
    super(sysDict);
  }

  /**
   * 创建字典
   */
  async createDict(createDictDto: CreateDictDto): Promise<IDict> {
    // 检查 code 是否已存在
    const isExist = await this.exists(eq(sysDict.code, createDictDto.code));
    if (isExist) {
      throw BizException.dictExist();
    }

    const created = await this.create(createDictDto);
    return toDict(created as SysDict);
  }

  /**
   * 更新字典
   */
  async updateDict(id: string, updateDictDto: UpdateDictDto): Promise<IDict> {
    // 如果更新 code，检查是否已存在
    if (updateDictDto.code) {
      const existing = await this.findOne(eq(sysDict.code, updateDictDto.code));
      if (existing && existing.id !== id) {
        throw BizException.dictExist();
      }
    }

    const updated = await this.update(id, updateDictDto);
    return toDict(updated as SysDict);
  }

  /**
   * 删除字典
   */
  async deleteDict(id: string): Promise<void> {
    // 检查是否有字典数据使用该字典
    const dictDataList = await db
      .select()
      .from(sysDictData)
      .where(and(eq(sysDictData.dictId, id), eq(sysDictData.isDeleted, false)))
      .limit(1);

    if (dictDataList.length > 0) {
      throw BizException.dictInUse();
    }

    await this.softDelete(id);
  }

  /**
   * 分页查询字典
   */
  async paginateDicts(query: QueryDictDto): Promise<IPaginationResponse<IDict>> {
    const conditions = [];

    if (query.code) {
      conditions.push(ilike(sysDict.code, `${query.code}%`));
    }
    if (query.name) {
      conditions.push(ilike(sysDict.name, `%${query.name}%`));
    }
    if (query.status !== undefined) {
      conditions.push(eq(sysDict.status, query.status));
    }

    const where = conditions.length > 0 ? and(...conditions) : undefined;
    const result = await this.paginate(query, where);
    return toDictPage(result as IPaginationResponse<SysDict>);
  }

  /**
   * 根据 code 查找字典
   */
  async findByCode(code: string): Promise<IDict | null> {
    const dict = (await this.findOne(eq(sysDict.code, code))) as SysDict | undefined;
    return dict ? toDict(dict) : null;
  }
}

